本文提及以下內容
了解Redux的概念可以追溯到先前facebook(現在改名叫做meta)公司的演講,他們提出MVC所遇到的問題以及提出flux的設計概念,本篇文章會重點式講述flux的概念,Redux是flux的概念底下所做出的一種實踐,redudx不單只是只能用在React,他是一種狀態管理的library,因此也會以原生js實作一個簡單的範例來理解redux的原理。
介紹flux之前我們先看flu字根的英文
從英文字母可以了解一切的根源在於流,flux主要也是在控管整個資料流動的設計。
在傳統MVC的設計模式會導致視圖(view)與模型的關係複雜,有可能一個視圖來自於不同的model,也可能導致無限循環的情形產生。如下圖
為了解決資料流混亂的問題,因此提出了flux的設計概念。
如下圖
flux設計模式提出,facebook也開源了flux的專案,但目前官方已經處於維護狀態並且推薦了其他狀態管理的library像是Redux、MobX、Recoil。
如下圖
圖片來源:facebook/flux
另外有興趣的人也可以觀看stack overflow的redux開發者的回答Why use Redux over Facebook Flux?更可以了解redux與flux的差別。
接下來講述redux發展的動機。
隨著Javascript單頁應用程式發展,需要管理許多狀態,這些狀態包含伺服器、資料暫存、本地端還沒有正式儲存到伺服器的資料等等,即便react簡化了事件流程,但state還是留給開發者自行管理
。
state狀態傳遞的時候遇到的瓶頸
在沒有Redux之前狀態是需要在各個component之間傳遞十分麻煩,有了Redux後將狀態統一儲存在store配發給每個component
UI接收到事件觸發後使用dispatch發送action到store,store經由所接收到的action到reducer處理對應的action後回傳state,UI接收到state
圖片來源Redux Application Data Flow
這邊以提款機範例展示Redux
提款機範例最小化redux基本要素包含以下
提款機範例中的角色各司其職
一個最基礎的action物件,帶有type的屬性,用來作為dispatch的參數,稍後將會被reducer函式接受做出對應的動作。
以此範例而言,action可以存款和提款
{
type: 'DEPOSIT'
}
{
type: 'WITHDRAW'
}
定義state的初始值的物件,換句話說算是資料的初始值,以此範例為一個key為money,值為1000的物件。
const initState = {
money: 1000
}
function ATMReducer(state = initState, action) {
switch (action.type) {
case 'DEPOSIT':
return { money: state.money + 100 }
case 'WITHDRAW':
return { money: state.money - 100 }
default:
return state
}
}
reducer作為改變state
的函式,負責邏輯處理
,這邊接收兩個參數,第一個參數是state的初始值
第二個參數是action
,透過switch用來辨認等等接收的dispatch的動作是哪一種類型,以此範例的話解析action的type
,將state的物件+100或-100,這邊可以發現撰寫方式是immutable
,我們不直接更改state裡面的值,而是創造一個新的物件return
回去。
//初始化一個store將reducer代入
let store = createStore(ATMReducer);
//當改變發生的時候要做什麼事情
//這裡帶入一個callback
//透過store.getState就可以讀取當前state的東西
store.subscribe(() => console.log(store.getState()));
//發送WITHDRAW的action
store.dispatch({
type: 'WITHDRAW'
});
store.dispatch({
type: 'DEPOSIT'
});
store.dispatch({
type: 'WITHDRAW'
});
完整程式碼如下
import { createStore } from 'redux'
const initState = {
money: 1000,
}
const depositActionCreator = (payload) => (
{
type: 'DEPOSIT',
payload
})
const withdrawActionCreator = (payload) => (
{
type: 'WITHDRAW', payload
}
)
function ATMReducer(state = initState, action) {
switch (action.type) {
case 'DEPOSIT':
return { money: state.money + action.payload }
case 'WITHDRAW':
return { money: state.money - action.payload }
default:
return state
}
}
let store = createStore(ATMReducer);
store.subscribe(() => console.log(store.getState()));
store.dispatch(depositActionCreator(100));
store.dispatch(withdrawActionCreator(200));
store.dispatch(depositActionCreator(500));
希望透過vanilla javascript可以更了解redux,如果內容有誤歡迎底下留言,希望以上內容對大家有所幫助。